package com.nengchuan.kbms.dfs.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nengchuan.config.exception.NcException;
import com.nengchuan.kbms.common.AutoWrapper;
import com.nengchuan.kbms.common.PageServiceImpl;
import com.nengchuan.kbms.dfs.dao.DataFileTagAttrMapper;
import com.nengchuan.kbms.dfs.entity.dto.*;
import com.nengchuan.kbms.dfs.entity.po.DataFileTagAttr;
import com.nengchuan.kbms.dfs.entity.po.DataTag;
import com.nengchuan.kbms.dfs.entity.po.DataTagAttr;
import com.nengchuan.kbms.dfs.dao.DataTagAttrMapper;
import com.nengchuan.kbms.dfs.entity.po.DataTagAttrOption;
import com.nengchuan.kbms.dfs.entity.vo.DataTagAttrVO;
import com.nengchuan.kbms.dfs.entity.vo.DataTagVO;
import com.nengchuan.util.MapperUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 标签属性 服务实现类
 * </p>
 *
 * @author abe
 * @since 2020-04-03
 */
@Service
public class DataTagAttrServiceImpl extends PageServiceImpl<DataTagAttrMapper, DataTagAttr> implements DataTagAttrService {

    @Autowired
    private DataTagAttrMapper dataTagAttrMapper;

    @Autowired
    private DataFileTagAttrMapper dataFileTagAttrMapper;

    @Autowired
    private DataTagAttrOptionService dataTagAttrOptionService;

    /**
     * 获取元数据详情
     * @param id 属性id
     * @return
     */
    @Override
    public DataTagAttrVO getAttr(Long id) {
        DataTagAttrVO dataTagAttrVO = getById(id, DataTagAttrVO.class);
        if (dataTagAttrVO != null) {
            // 设置属性
            QueryWrapper<DataTagAttrOption> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(DataTagAttrOption::getAttrId, id);
            List<DataTagAttrOptionDTO> optionDTOList = dataTagAttrOptionService.list(wrapper, DataTagAttrOptionDTO.class);
            dataTagAttrVO.setDataTagAttrOptionDTOList(optionDTOList);
        }
        return dataTagAttrVO;
    }

    /**
     * 新增元数据属性：
     * 1. 通过元数据类型，名称；编号 检查元数据属性是否存在，存在不允许新增
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveAttr(DataTagAttrDTO dto) {
        Objects.requireNonNull(dto);

        QueryWrapper<DataTagAttr> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(DataTagAttr::getTagId, dto.getTagId())
                .eq(DataTagAttr::getAttrName, dto.getAttrName());
        DataTagAttr dataTagAttr = getOne(wrapper, false);
        if (dataTagAttr != null) {
            throw new NcException("新增失败，属性名称已存在");
        }
        // 单独验证编号，编号规则
        wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(DataTagAttr::getAttrNo, dto.getAttrNo());
        dataTagAttr = getOne(wrapper, false);
        if (dataTagAttr != null) {
            throw new NcException("新增失败，属性编号已存在");
        }
        // 设置排序
        Integer maxSortNo = dataTagAttrMapper.getMaxSortNo(dto.getTagId());
        if (maxSortNo == null) {
            maxSortNo = 0;
        }
        dto.setSortNo(maxSortNo + 10);
        Long attrId = insert(dto).getId();
        // 保存属性选项值
        if (CollectionUtils.isNotEmpty(dto.getDataTagAttrOptionDTOList())) {
            List<DataTagAttrOption> optionList = MapperUtils.mappingList(dto.getDataTagAttrOptionDTOList(), DataTagAttrOption.class);
            for (int i = 0; i < optionList.size(); i++) {
                DataTagAttrOption dataTagAttrOption = optionList.get(i);
                dataTagAttrOption.setId(null);
                dataTagAttrOption.setAttrId(attrId);
            }
            dataTagAttrOptionService.saveBatch(optionList);
        }
        return attrId;
    }

    /**
     * 元数据属性修改
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAttr(DataTagAttrDTO dto) {
        Objects.requireNonNull(dto);
        Objects.requireNonNull(dto.getId(), "主键不能为空");

        // 检查修改名称和编号 ，不允许重复
        QueryWrapper<DataTagAttr> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(DataTagAttr::getTagId, dto.getTagId())
                .eq(DataTagAttr::getAttrName, dto.getAttrName())
                .ne(DataTagAttr::getId, dto.getId());
        DataTagAttr dataTagAttr = getOne(wrapper, false);
        if (dataTagAttr != null) {
            throw new NcException("修改失败，属性名称已存在");
        }
        wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(DataTagAttr::getAttrNo, dto.getAttrNo())
                .ne(DataTagAttr::getId, dto.getId());
        dataTagAttr = getOne(wrapper, false);
        if (dataTagAttr != null) {
            throw new NcException("修改失败，编号已存在");
        }
        update(dto);
        if (CollectionUtils.isNotEmpty(dto.getDataTagAttrOptionDTOList())) {
            List<DataTagAttrOption> optionList = MapperUtils.mappingList(dto.getDataTagAttrOptionDTOList(), DataTagAttrOption.class);
            for (int i = 0; i < optionList.size(); i++) {
                DataTagAttrOption dataTagAttrOption = optionList.get(i);
                dataTagAttrOption.setAttrId(dto.getId());
            }
            // 移除 id 不在 optionList 中的数据
            List<Long> optionIdList = optionList.stream().map(DataTagAttrOption::getId).filter(id -> id != null).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(optionIdList)) {
                QueryWrapper<DataTagAttrOption> optionWrapper = new QueryWrapper<>();
                optionWrapper.lambda().eq(DataTagAttrOption::getAttrId, dto.getId())
                        .notIn(DataTagAttrOption::getId, optionIdList);
                dataTagAttrOptionService.remove(optionWrapper);
            }
            dataTagAttrOptionService.saveOrUpdateBatch(optionList);
        }
        return true;
    }

    /**
     * 删除元数据属性
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAttr(Serializable id) {
        Objects.requireNonNull(id);
        boolean flag = remove(id);
        if (flag) {
            // 移除属性选项
            List<Long> attrIdList = transIdToList(id);
            QueryWrapper<DataTagAttrOption> wrapper = new QueryWrapper<>();
            wrapper.lambda().in(DataTagAttrOption::getAttrId, attrIdList);
            return dataTagAttrOptionService.remove(wrapper);
        }
        return false;
    }

    /**
     * 属性排序交换
     */
    @Override
    public boolean swap(DataTagAttrSortSwapDTO dto) {
        Objects.requireNonNull(dto);
        DataTagAttr dataTagAttr1 = getById(dto.getAttrId1());
        DataTagAttr dataTagAttr2 = getById(dto.getAttrId2());
        if (dataTagAttr1 != null && dataTagAttr2 != null) {
            Integer tempSort = dataTagAttr1.getSortNo();
            dataTagAttr1.setSortNo(dataTagAttr2.getSortNo().intValue());
            dataTagAttr2.setSortNo(tempSort);
            return updateBatchById(Arrays.asList(dataTagAttr1, dataTagAttr2));
        }
        return false;
    }

    /**
     * 元数据属性列表
     */
    @Override
    public List<DataTagAttr> listAttr(DataTagAttrListDTO dto) {
        QueryWrapper<DataTagAttr> wrapper = new AutoWrapper<>(dto);
        wrapper.lambda().orderByAsc(DataTagAttr::getSortNo);
        return list(wrapper);
    }

    /**
     * 保存文件和标签属性关联表
     */
    @Override
    public void saveFileTagAttr(DataFileTagAttrDTO dataFileTagAttrDTO) {
        DataFileTagAttr dataFileTagAttr = MapperUtils.mapping(dataFileTagAttrDTO, DataFileTagAttr.class);
        dataFileTagAttrMapper.insert(dataFileTagAttr);
    }

}
